package com.pivotal.cloud.security.password;

import com.pivotal.cloud.crypto.codec.Hex;
import com.pivotal.cloud.crypto.keygen.BytesKeyGenerator;
import com.pivotal.cloud.crypto.keygen.KeyGenerators;
import com.pivotal.cloud.crypto.utils.EncodingUtil;

import java.security.MessageDigest;

/**
 * @className: AbstractPasswordEncoder
 * @projectName: PivotalCloud项目
 * @module: PivotalCloud项目-AbstractPasswordEncoder类，主要位于Security安全模块-密码加密抽象接口模块
 * @content: AbstractPasswordEncoder-密码加密抽象接口
 * @author: Powered by Marklin
 * @datetime: 2025-06-24 15:01
 * @version: 1.0.0
 * @copyright: Copyright © 2018-2025 PivotalCloud Systems Incorporated. All rights
 * reserved.
 */
public abstract class AbstractPasswordEncoder implements PasswordEncoder {

	private final BytesKeyGenerator saltGenerator = KeyGenerators.secureRandom();

	protected AbstractPasswordEncoder() {
	}

	protected abstract byte[] encode(CharSequence rawPassword, byte[] salt);

	protected byte[] encodeAndConcatenate(CharSequence rawPassword, byte[] salt) {
		return EncodingUtil.concatenate(salt, this.encode(rawPassword, salt));
	}

	protected static boolean matches(byte[] expected, byte[] actual) {
		return MessageDigest.isEqual(expected, actual);
	}

	/**
	 * 密码加密
	 * @param rawPassword 原始密码
	 * @return 返回结果
	 */
	@Override
	public String encode(CharSequence rawPassword) {
		byte[] salt = this.saltGenerator.generateKey();
		byte[] encoded = this.encodeAndConcatenate(rawPassword, salt);
		return String.valueOf(Hex.encode(encoded));
	}

	/**
	 * 验证密码
	 * @param rawPassword 原始密码
	 * @param encodedPassword 加密密码
	 * @return 返回结果
	 */
	@Override
	public boolean matches(CharSequence rawPassword, String encodedPassword) {
		byte[] digest = Hex.decode(encodedPassword);
		byte[] salt = EncodingUtil.subArray(digest, 0, this.saltGenerator.getKeyLength());
		return matches(digest, this.encodeAndConcatenate(rawPassword, salt));
	}

}
